/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.controller.datasource;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.je.common.base.DynaBean;
import com.je.common.base.controller.CommonTreeController;
import com.je.common.base.mvc.BaseMethodArgument;
import com.je.common.base.result.BaseRespResult;
import com.je.common.base.result.DirectJsonResult;
import com.je.common.base.service.CommonCheckService;
import com.je.common.base.table.ParseBuildingSqlFactory;
import com.je.common.base.util.MessageUtils;
import com.je.common.base.util.StringUtil;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.constant.DataSourceTypeCons;
import com.je.meta.model.view.QueryConfigVo;
import com.je.meta.model.view.ViewDdlVo;
import com.je.meta.service.datasource.DataSourceService;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.sql.SQLSyntaxErrorException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 图表和报表的数据源
 */
@RestController
@RequestMapping(value = "/je/meta/dataSource")
public class DataSourceController extends CommonTreeController {

    @Autowired
    private DataSourceService dataSourceService;
    @Autowired
    private CommonCheckService commonCheckService;




    @RequestMapping(value = "/getDsTree", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult getTreeData(BaseMethodArgument param, HttpServletRequest request) {
        String chartId = getStringParameter(request,"JE_CORE_CHARTS_ID");
        JSONTreeNode tree = dataSourceService.getDsTree(chartId);
        return tree != null ? BaseRespResult.successResult(DirectJsonResult.buildObjectResult(tree)) : BaseRespResult.successResult(DirectJsonResult.buildObjectResult("{}"));
    }

    /**
     * 引入数据源
     * @param param
     * @param request
     * @return
     */
    @RequestMapping(value = "/preAddDataSource", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult preAddDataSource(BaseMethodArgument param, HttpServletRequest request) {
        String dataSourceIds = getStringParameter(request,"dataSourceIds");
        List<JSONTreeNode> list = dataSourceService.getPreAddDataSource(dataSourceIds);
        return list != null ? BaseRespResult.successResult(list) : BaseRespResult.successResult(DirectJsonResult.buildObjectResult("{}"));
    }

    @Override
    @RequestMapping(value = "/doSave", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult doSave(BaseMethodArgument param, HttpServletRequest request) {
        //判断DATASOURCE_CODE是否重复
        DynaBean dynaBean = (DynaBean) request.getAttribute("dynaBean");
        String code = dynaBean.getStr("DATASOURCE_CODE");
        boolean result = commonCheckService.checkRepeat(ConditionsWrapper.builder().table("JE_CORE_DATASOURCE").eq("DATASOURCE_CODE",code));
        if(result){
            return BaseRespResult.errorResult(MessageUtils.getMessage("common.code.repeat",code));
        }
        return super.doSave(param, request);
    }

    @Override
    @RequestMapping(value = "/doUpdate", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult doUpdate(BaseMethodArgument param, HttpServletRequest request) {
        //判断DATASOURCE_CODE是否重复
        DynaBean dynaBean = (DynaBean) request.getAttribute("dynaBean");
        String code = dynaBean.getStr("DATASOURCE_CODE");
        String pkValue = param.getPkValue();
        boolean result = commonCheckService.checkRepeat(ConditionsWrapper.builder()
                .table("JE_CORE_DATASOURCE")
                .eq("DATASOURCE_CODE",code)
                .ne("JE_CORE_DATASOURCE_ID",pkValue));
        if(result){
            return BaseRespResult.errorResult(MessageUtils.getMessage("common.code.repeat",code));
        }
        dynaBean.setStr("masterTableId",getStringParameter(request,"masterTableId"));
        dataSourceService.doUpdate(dynaBean);
        return BaseRespResult.successResult(dynaBean);
    }

    @Override
    @RequestMapping(value = "/doCopy", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult doCopy(BaseMethodArgument param, HttpServletRequest request) {
        DynaBean dynaBean = (DynaBean) request.getAttribute("dynaBean");
        String code = dynaBean.getStr("DATASOURCE_CODE");
        boolean result = commonCheckService.checkRepeat(ConditionsWrapper.builder().table("JE_CORE_DATASOURCE").eq("DATASOURCE_CODE",code));
        if(result){
            return BaseRespResult.errorResult(MessageUtils.getMessage("common.code.repeat",code));
        }
        String targetId = getStringParameter(request,"targetId");
        dynaBean.setStr("targetId",targetId);
        dataSourceService.doCopy(dynaBean);
        return BaseRespResult.successResult(MessageUtils.getMessage("common.operation.success"));
    }

    @Override
    @RequestMapping(value = "/doRemove", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult doRemove(BaseMethodArgument param, HttpServletRequest request) {
        //判断是否有子集
        String id = param.getIds();
        boolean result = commonCheckService.checkRepeat(ConditionsWrapper.builder().table("JE_CORE_DATASOURCE").eq("SY_PARENT",id));
        if(result){
            return BaseRespResult.errorResult(MessageUtils.getMessage("common.exist.child"));
        }
        return super.doRemove(param, request);
    }

    @RequestMapping(value = "/getSelectModel", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult getSelectModel(BaseMethodArgument param, HttpServletRequest request) {
        String sql = getStringParameter(request,"sql");
        String trSql = sql.trim().toUpperCase();
        if(!trSql.startsWith("SELECT")){
            return BaseRespResult.errorResult(MessageUtils.getMessage("dataSource.sql.error"));
        }
        return BaseRespResult.successResult( dataSourceService.getSelectModel(sql));
    }


    /**
     * 根据表编码获取DDL
     */
    @RequestMapping(value = "/getSelectDdlByTableId", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult getSelectDdlByTableId(BaseMethodArgument param, HttpServletRequest request) {
        String resourceId = getStringParameter(request, "JE_CORE_RESOURCETABLE_ID");
        if (StringUtil.isEmpty(resourceId)) {
            return BaseRespResult.errorResult(MessageUtils.getMessage("common.params.canotEmpty","JE_CORE_DATASOURCE_ID"));
        }
        String ddl = dataSourceService.getSelectDdl(resourceId);
        try {
            ddl = ParseBuildingSqlFactory.build().beautifyCreateViewDdl(ddl);
        } catch (SQLSyntaxErrorException e) {
            e.printStackTrace();
        }
        return BaseRespResult.successResult(ddl);
    }

    /**
     * 根据配置获取DDL
     */
    @RequestMapping(value = "/getSelectDdlByConfig", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult getSelectDdlByConfig(BaseMethodArgument param, HttpServletRequest request) {
        String type = getStringParameter(request,"DATASOURCE_TYPE");
        ViewDdlVo viewDdlVo=JSONObject.parseObject(param.getStrData(), ViewDdlVo.class);
        String ddl =dataSourceService.getSelectDdlByConfig(type,viewDdlVo);
        try {
            ddl = ParseBuildingSqlFactory.build().beautifyCreateViewDdl(ddl);
        } catch (SQLSyntaxErrorException e) {
            e.printStackTrace();
        }
        return BaseRespResult.successResult(ddl);
    }

    /**
     * 根据表编码获取DDL
     */
    @RequestMapping(value = "/getfields", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult getfields(BaseMethodArgument param, HttpServletRequest request) {
        String JE_CORE_DATASOURCE_ID = getStringParameter(request,"JE_CORE_DATASOURCE_ID");
        String tableCode = getStringParameter(request,"tableCode");
        String fields = dataSourceService.getFieldsBySql(JE_CORE_DATASOURCE_ID,tableCode);
        return BaseRespResult.successResult(fields);
    }
    /**
     * 根据数据源ID获取参数信息
     */
    @RequestMapping(value = "/getDataSourceParameter", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult getDataSourceParameter(BaseMethodArgument param, HttpServletRequest request) {
        if(StringUtil.isEmpty(getStringParameter(request,"ids"))){
            return BaseRespResult.errorResult(MessageUtils.getMessage("common.params.canotEmpty","ids"));
        }
        JSONObject data = dataSourceService.getDataSourceParameter(getStringParameter(request,"ids"));
        return BaseRespResult.successResult(data);
    }

    /**
     * 同时执行多个数据源
     */
    @RequestMapping(value = "/batchExecute", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult batchExecute(BaseMethodArgument param, HttpServletRequest request) {
        if(StringUtil.isEmpty(getStringParameter(request,"strData"))){
            return BaseRespResult.errorResult(MessageUtils.getMessage("common.params.canotEmpty","JE_CORE_DATASOURCE_ID"));
        }
        JSONObject data = dataSourceService.batchExecute(getStringParameter(request,"strData"));
        return BaseRespResult.successResult(data);
    }


    /**
     * 根据表编码获取DDL
     */
    @RequestMapping(value = "/execute", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult executeSql(BaseMethodArgument param, HttpServletRequest request) {
        String id =getStringParameter(request,"JE_CORE_DATASOURCE_ID");
        String config = getStringParameter(request,"config");
        String parameterStr = getStringParameter(request,"parameterStr");
        String limit = getStringParameter(request,"limit");
        List<Map<String,Object>> list = dataSourceService.execute(config,id, parameterStr,limit);
        Map<String,Object> result = new HashedMap();
        result.put("count",list==null?0:list.size());
        result.put("listData",list);
        return BaseRespResult.successResult(result);
    }


    @RequestMapping(value = "/testExecute", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult testExecute(BaseMethodArgument param, HttpServletRequest request) {
        String code =getStringParameter(request,"DATASOURCE_CODE");
        String parameterStr = getStringParameter(request,"parameterStr");
        String limit = getStringParameter(request,"limit");
        if(StringUtil.isEmpty(limit)){
            limit="0";
        }
        Map<String,Object> map = new HashMap<>();
        if(StringUtil.isNotEmpty(parameterStr)){
            map = JSON.parseObject(parameterStr);
        }
        return BaseRespResult.successResult(dataSourceService.executeForRpc(code,map,Integer.parseInt(limit)));
    }
}
